﻿using Microsoft.VisualBasic;
using Microsoft.VisualBasic.FileIO;
using SqlSugar;
using SqlSugar.Extensions;
using System.Drawing.Printing;
using System.Linq.Expressions;
using Zhao.Common.EnumEntity;
using Zhao.Common.Helper;
using Zhao.Common.Helper.Zhao.Arena;
using Zhao.IServer.Field;
using Zhao.IServer.Log;
using Zhao.Models.AppletDto;
using Zhao.Models.DTO;
using Zhao.Models.Entity;
using Zhao.Repository.Base;
using Zhao.Repository.UnitOfWork;

namespace Zhao.Service.Field
{
    /// <summary>
    /// 场地
    /// </summary>
    public class FieldsServer : BaseService<Fields>, IFieldsServer
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IBaseRepository<Appointments> AppRepository;
        private readonly HolidayChecker _holidayChecker;
        private readonly ILogsServer _logs;

        public FieldsServer(IBaseRepository<Fields> baseDal, IUnitOfWork unitOfWork,HolidayChecker holidayChecker, ILogsServer logs) : base(baseDal, unitOfWork)
        {
            _unitOfWork = unitOfWork;
            _holidayChecker= holidayChecker;
            _logs= logs;
        }

        /// <summary>
        /// 获取场地信息
        /// </summary>
        /// <param name="expressionable"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<PageModel<FieldDto>> FieldsQuery(Expression<Func<Fields, Venues, FieldTypes, bool>> expressionable, int pageIndex, int pageSize)
        {
            //获取总条数
            RefAsync<int> totalCount = 0;

            var list = await _Client.Queryable<Fields>()
                .LeftJoin<Venues>((a, b) => a.VenueID == b.VenueID)
                .LeftJoin<FieldTypes>((a, b, c) => a.FieldTypeID == c.FieldTypeID)
                .WhereIF(expressionable != null, expressionable)
                .Select((a, b, c) => new FieldDto
                {
                    id = a.FieldID,
                    VenueName = b.VenueName,
                    TypeName = c.FieldTypeName,
                    FieldName = a.FieldName,
                    Status = a.Status,
                    TId = a.FieldTypeID,
                    VId = a.VenueID
                }).ToPageListAsync(pageIndex, pageSize, totalCount).ConfigureAwait(false);

            int totalPage = Math.Ceiling(totalCount.ObjToDecimal() / pageSize.ObjToDecimal()).ObjToInt();

            return new PageModel<FieldDto>() { count = totalCount, PageCount = totalPage, PageIndex = pageIndex, PageSize = pageSize, data = list, code = totalCount == 0 ? -1 : 0, msg = totalCount == 0 ? "未查询到任何数据" : "" };
        }

        /// <summary>
        /// 获取球馆预约不同时间段的价格和场地预约信息
        /// </summary>
        /// <param name="expressionable"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="display"></param>
        /// <returns></returns>
        public async Task<PageModel<VenuePricingDTO>> SessionPriceQuery(Expression<Func<Venues, Fields, bool>> expressionable, int pageIndex, int pageSize, string display,int order)
        {
            //获取总条数
            RefAsync<int> totalCount = 0;

            //时间转换判断display是否是周末或节假日
            var weekend = await _holidayChecker.IsHolidayOrWeekend(display.ToDateTime());

            var list = await _Client.Queryable<Venues>()
                .LeftJoin<Fields>((a, b) => a.VenueID == b.VenueID)
                .GroupBy((a, b) => new { b.FieldID, b.FieldName, b.FieldTypeID, a.VenueID })
                .WhereIF(expressionable != null, expressionable)
                .Select((a, b) => new VenuePricingDTO
                {
                    fId = b.FieldID,
                    fName = b.FieldName,
                    TimePrices = SqlFunc.Subqueryable<FacilityTimePrice>().Where(f => f.VenueID == a.VenueID && f.FacilityType_id == b.FieldTypeID && f.IsWeekend == weekend).ToList(f => new TimePrice
                    {
                        StartTime = f.StartTime,
                        EndTime = f.EndTime,
                        IsWeekend = f.IsWeekend,
                        Price = f.Price
                    }),
                    Bookings = SqlFunc.Subqueryable<Appointments>().Where((g) => b.FieldID == g.FieldID && g.DisplayDate == display && g.Status != (short)AppointmentStatus.Canceled).ToList((g) => new Booking
                    {
                        Id = g.AppointmentID,
                        StartTime = g.StartTime,
                        EndTime = g.EndTime,
                        status = g.Status,
                        userName = g.Name,
                        phone = g.Mobile.Substring(g.Mobile.Length - 4, 4),
                    }),
                    BookingCount = SqlFunc.Subqueryable<Appointments>().Where((g) => b.FieldID == g.FieldID && g.DisplayDate == display && g.Status != (short)AppointmentStatus.Canceled).Count()
                })
                .MergeTable()//需要加上MergeTable对Select后的对象进行排序
                .OrderByIF(order!=0,a=>a.BookingCount)
                .ToPageListAsync(pageIndex, pageSize, totalCount).ConfigureAwait(false);
            int totalPage = Math.Ceiling(totalCount.ObjToDecimal() / pageSize.ObjToDecimal()).ObjToInt();

            return new PageModel<VenuePricingDTO>() { count = totalCount, PageCount = totalPage, PageIndex = pageIndex, PageSize = pageSize, data = list, code = totalCount == 0 ? -1 : 0, msg = totalCount == 0 ? "未查询到任何数据" : "" };
        }

        /// <summary>
        /// 获取场地不同时段价格（简化版）
        /// </summary>
        /// <param name="expressionable">查询条件</param>
        /// <param name="display">日期</param>
        /// <returns>场地价格和预约信息列表</returns>
        public async Task<List<VenuePricingSimpleDTO>> SessionPriceSimpleQuery(Expression<Func<Venues, Fields, bool>> expressionable, string display)
        {
            //判断是否是周末或节假日
            var weekend = await _holidayChecker.IsHolidayOrWeekend(display.ToDateTime());

            var list = await _Client.Queryable<Venues>()
                .LeftJoin<Fields>((a, b) => a.VenueID == b.VenueID)
                .WhereIF(expressionable != null, expressionable)
                .Select((a, b) => new VenuePricingSimpleDTO
                {
                    fId = b.FieldID,
                    fName = b.FieldName,
                    TimePrices = SqlFunc.Subqueryable<FacilityTimePrice>()
                        .Where(f => f.VenueID == a.VenueID && f.FacilityType_id == b.FieldTypeID && f.IsWeekend == weekend)
                        .ToList(f => new TimePrice
                        {
                            StartTime = f.StartTime,
                            EndTime = f.EndTime,
                            IsWeekend = f.IsWeekend,
                            Price = f.Price
                        }),
                    Bookings = SqlFunc.Subqueryable<Appointments>()
                        .Where((g) => b.FieldID == g.FieldID && g.DisplayDate == display && g.Status != (short)AppointmentStatus.Canceled)
                        .ToList((g) => new BookingSimple
                        {
                            Id = g.AppointmentID,
                            StartTime = g.StartTime.ToString(),
                            EndTime = g.EndTime.ToString(),
                            status = g.Status
                        })
                })
                .ToListAsync()
                .ConfigureAwait(false);

            return list;
        }


        /// <summary>
        /// 更新已完成的场地预约状态
        /// </summary>
        /// <returns>更新的记录数</returns>
        public async Task<int> UpdateCompletedAppointmentsAsync()
        {
            int updateCount = 0;

            // 获取今天的年月日
            var date = DateTime.Today.ToString("yyyy-MM-dd");

            // 获取当前时间的 TimeSpan
            TimeSpan currentTime = DateTime.Now.TimeOfDay;

            // 开启事务
            await _Client.Ado.UseTranAsync(async () =>
            {
                try
                {
                    // 1. 查询今天的预约
                    var expiredAppointments = await _Client.Queryable<Appointments>()
                        .Where(x =>
                            x.DisplayDate.Equals(date) &&
                            x.Status == (short)AppointmentStatus.Reserved
                        ).ToListAsync();

                    // 在内存中比较 TimeSpan
                    var appointmentsToUpdate = expiredAppointments
                        .Where(x => currentTime >= TimeSpan.Parse(x.EndTime.ToString("HH:mm:ss")))
                        .ToList();

                    if (appointmentsToUpdate.Any())
                    {
                        foreach (var appointment in appointmentsToUpdate)
                        {
                            appointment.Status = (short)AppointmentStatus.Completed;
                            appointment.UpdatedAt = DateTime.Now;
                        }

                        updateCount = await _Client.Updateable(appointmentsToUpdate)
                            .UpdateColumns(x => new
                            {
                                x.Status,
                                x.UpdatedAt
                            })
                            .ExecuteCommandAsync();
                        await _logs.Info($"场地预约状态已更新：{updateCount}条记录修改为已完成状态");
                    }
                }
                catch (Exception ex)
                {
                    await _logs.Error($"更新场地预约状态失败：{ex.Message}");
                    throw; // 抛出异常会自动回滚事务
                }
            });

            return updateCount;
        }

        #region 小程序API
        public async Task<PageModel<VenuesFieldsInfo>> GetVenueFieldsInfo(Guid venueId, int pageIndex, int pageSize)
        {
            // 获取总条数
            RefAsync<int> totalCount = 0;

            // 获取最近5天的日期
            var dates = Enumerable.Range(0, 5)
                .Select(i => DateTime.Now.AddDays(i).ToString("yyyy-MM-dd"))
                .ToList();

            // 获取指定球馆下所有去重的场地类型信息（分页）
            var fieldTypeInfo = await _Client.Queryable<Fields, FieldTypes>((f, ft) => f.FieldTypeID == ft.FieldTypeID)
                .Where((f, ft) => f.VenueID == venueId && f.Status == 3)
                .Select((f, ft) => new VenuesFieldsInfo
                {
                    Id = ft.FieldTypeID,
                    Name = ft.FieldTypeName
                })
                .Distinct()
                .ToPageListAsync(pageIndex, pageSize, totalCount)
                .ConfigureAwait(false);

            // 查询工作日最小价格数据
            var weekdayData = _Client.Queryable<FacilityTimePrice>()
                .Where(f => f.IsWeekend == false)
                .GroupBy(f => new { f.FacilityType_id })
                .Select(f => new
                {
                    FieldTypeID = f.FacilityType_id,
                    IsWeekend = false,
                    MinPrice = SqlFunc.AggregateMin(f.Price)
                })
                .ToList();

            // 查询周末最小价格数据
            var weekendData = _Client.Queryable<FacilityTimePrice>()
                .Where(f => f.IsWeekend == true)
                .GroupBy(f => new { f.FacilityType_id })
                .Select(f => new
                {
                    FieldTypeID = f.FacilityType_id,
                    IsWeekend = true,
                    MinPrice = SqlFunc.AggregateMin(f.Price)
                })
                .ToList();

            // 将数据转换为字典结构，便于快速查找
            var weekdayDict = weekdayData.ToDictionary(p => p.FieldTypeID, p => p.MinPrice);
            var weekendDict = weekendData.ToDictionary(p => p.FieldTypeID, p => p.MinPrice);

            // 并发判断日期是否为节假日或周末
            var dateCheckTasks = dates.Select(async dateStr => new
            {
                DateStr = dateStr,
                DateShort = dateStr.Substring(5),
                IsWeekendOrHoliday = await _holidayChecker.IsHolidayOrWeekend(DateTime.Parse(dateStr))
            }).ToList();

            var dateInfoList = await Task.WhenAll(dateCheckTasks);

            // 构建最终结果
            foreach (var typeInfo in fieldTypeInfo)
            {
                typeInfo.datePricePairs = new List<DatePricePair>();

                foreach (var dateInfo in dateInfoList)
                {
                    var minPrice = dateInfo.IsWeekendOrHoliday
                        ? (weekendDict.TryGetValue(typeInfo.Id, out var weekendPrice) ? weekendPrice : 0)
                        : (weekdayDict.TryGetValue(typeInfo.Id, out var weekdayPrice) ? weekdayPrice : 0);

                    typeInfo.datePricePairs.Add(new DatePricePair
                    {
                        Date = dateInfo.DateShort,
                        Price = minPrice
                    });
                }
            }

            // 构建分页对象
            int totalPage = Math.Ceiling(totalCount.ObjToDecimal() / pageSize.ObjToDecimal()).ObjToInt();

            return new PageModel<VenuesFieldsInfo>()
            {
                count = totalCount,
                PageCount = totalPage,
                PageIndex = pageIndex,
                PageSize = pageSize,
                data = fieldTypeInfo,
                code = totalCount == 0 ? -1 : 0,
                msg = totalCount == 0 ? "未查询到任何数据" : ""
            };
        }
        #endregion

    }
}
